/**
 * Image Processor - Image compression and format conversion
 * 
 * Features:
 * - Compress images to reduce size
 * - Convert to supported formats
 * - Resize large images
 * - Maintain aspect ratio
 */

export interface ImageProcessOptions {
  maxWidth?: number;
  maxHeight?: number;
  quality?: number; // 0.0 to 1.0
  format?: 'image/jpeg' | 'image/png' | 'image/webp';
}

const DEFAULT_OPTIONS: Required<ImageProcessOptions> = {
  maxWidth: 2048,
  maxHeight: 2048,
  quality: 0.85,
  format: 'image/jpeg',
};

/**
 * Compress and resize image
 */
export async function processImage(
  file: File,
  options: ImageProcessOptions = {}
): Promise<{ blob: Blob; base64: string; dataUrl: string }> {
  const opts = { ...DEFAULT_OPTIONS, ...options };

  return new Promise((resolve, reject) => {
    const img = new Image();
    const reader = new FileReader();

    reader.onload = (e) => {
      img.src = e.target?.result as string;
    };

    img.onload = () => {
      try {
        // Calculate new dimensions
        let { width, height } = img;
        
        if (width > opts.maxWidth || height > opts.maxHeight) {
          const ratio = Math.min(opts.maxWidth / width, opts.maxHeight / height);
          width = Math.round(width * ratio);
          height = Math.round(height * ratio);
        }

        // Create canvas
        const canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;

        const ctx = canvas.getContext('2d');
        if (!ctx) {
          reject(new Error('Failed to get canvas context'));
          return;
        }

        // Draw image
        ctx.drawImage(img, 0, 0, width, height);

        // Convert to blob
        canvas.toBlob(
          (blob) => {
            if (!blob) {
              reject(new Error('Failed to create blob'));
              return;
            }

            // Convert to base64
            const reader = new FileReader();
            reader.onloadend = () => {
              const dataUrl = reader.result as string;
              const base64 = dataUrl.split(',')[1];
              resolve({ blob, base64, dataUrl });
            };
            reader.onerror = reject;
            reader.readAsDataURL(blob);
          },
          opts.format,
          opts.quality
        );
      } catch (error) {
        reject(error);
      }
    };

    img.onerror = () => {
      reject(new Error('Failed to load image'));
    };

    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

/**
 * Get image dimensions
 */
export async function getImageDimensions(file: File): Promise<{ width: number; height: number }> {
  return new Promise((resolve, reject) => {
    const img = new Image();
    const reader = new FileReader();

    reader.onload = (e) => {
      img.src = e.target?.result as string;
    };

    img.onload = () => {
      resolve({ width: img.width, height: img.height });
    };

    img.onerror = reject;
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

/**
 * Validate image file
 */
export function validateImage(file: File, options: {
  maxSizeBytes?: number;
  allowedTypes?: string[];
} = {}): { valid: boolean; error?: string } {
  const {
    maxSizeBytes = 10 * 1024 * 1024, // 10MB
    allowedTypes = ['image/png', 'image/jpeg', 'image/jpg', 'image/webp', 'image/gif'],
  } = options;

  // Check type
  if (!allowedTypes.includes(file.type)) {
    return {
      valid: false,
      error: `不支持的文件类型: ${file.type}。支持: ${allowedTypes.join(', ')}`,
    };
  }

  // Check size
  if (file.size > maxSizeBytes) {
    const maxMB = (maxSizeBytes / 1024 / 1024).toFixed(1);
    const actualMB = (file.size / 1024 / 1024).toFixed(1);
    return {
      valid: false,
      error: `文件过大: ${actualMB}MB (最大 ${maxMB}MB)`,
    };
  }

  return { valid: true };
}

/**
 * Convert File to base64
 */
export async function fileToBase64(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      const dataUrl = reader.result as string;
      const base64 = dataUrl.split(',')[1];
      resolve(base64);
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

/**
 * Get image MIME type from base64
 */
export function getMimeTypeFromBase64(base64: string): string {
  const match = base64.match(/^data:([^;]+);/);
  return match ? match[1] : 'image/png';
}

/**
 * Compress image if needed
 */
export async function compressIfNeeded(
  file: File,
  maxSizeBytes: number = 1024 * 1024 // 1MB
): Promise<{ file: File | Blob; compressed: boolean; originalSize: number; newSize: number }> {
  if (file.size <= maxSizeBytes) {
    return {
      file,
      compressed: false,
      originalSize: file.size,
      newSize: file.size,
    };
  }

  // Calculate quality based on current size
  const ratio = maxSizeBytes / file.size;
  const quality = Math.max(0.5, Math.min(0.9, ratio * 0.9));

  const { blob } = await processImage(file, { quality });

  return {
    file: blob,
    compressed: true,
    originalSize: file.size,
    newSize: blob.size,
  };
}

